package msu.ml.data;
import weka.core.*;

/**
 * Classifies probability distributions using a threshold rule. For
 * a specified class, the rule will only classify the distribution as
 * that class if it exceeds a specified threshold, otherwise a class
 * is chosen from the remaining candidates using a majority wins rule.
 *
 * @author Reginald M Mead
 * @version 1.0
 *
 * @see ClassificationRule
 * @see MajorityRule
 */
public class ThresholdRule extends ClassificationRule 
{
   private int target;
   private double threshold;

	/**
	 * Creates a new threshold rule with a default target
	 * class of 1 and a default threshold of 70%
	 */
   public ThresholdRule()
   {
      this.target = 1;
      this.threshold = .7;
   }
      
	/** 
	 * Creates a new threshold rule with the specified
	 * threshold and target class.
	 *
	 * @param threshold threshold that must be exceeded to classify distribution as target class.
	 * @param target target class that must exceed threshold
	 */
   public ThresholdRule(double threshold, int target)
   {
      this.target = target;
      this.threshold = threshold;
   }

	/**
	 * Classifies a distribution using threshold rules. Only 
	 * returns target if distribution[target] &gt; threshold.
	 *
	 * @param distribution distribution to classify
	 */
	public int getClassFromDistribution(double [] distribution)
	{
      if(distribution[target] > threshold)
         return target;

      int highIndex = (target == 0) ? 1 : 0;
      for(int i = 0; i < distribution.length; i++)
      {
         if(distribution[i] > distribution[highIndex] && i != target)
            highIndex = i;
      }
      return highIndex;
   }

	/**
	 * Classifies a set of frequencies using threshold rules. Only 
	 * returns target if (freq[target] / total) &gt; threshold.
	 *
	 * @param freq set of frequencies to classify
	 */
   public int getClassFromDistribution(int [] freq)
   {
      int total = 0;
      for(int i = 0; i < freq.length; i++)
         total += freq[i];

      double [] dist = new double[freq.length];

      for(int i = 0; i < freq.length; i++)
         dist[i] = (double)freq[i] / (double)total;

      return getClassFromDistribution(dist);
   }
}
